<template>
  <ActionBar />
  <div class="weather-panel" data-tauri-drag-region>
    <!-- 顶部城市和当前温度 -->
    <div class="weather-header">
      <n-cascader class="city" v-model:value="city.value" placeholder="请选择城市" :expand-trigger="`hover`"
        :options="cityOptions" :check-strategy="`child`" :show-path="false" @update:value="handleCityUpdate"
        :remote="true" :on-load="handleLoad" />
      <div v-if="current.alert" class="alert">{{ current.alert }}</div>
    </div>
    <div class="weather-current">
      <span class="current-temp">{{ current.temp }}°</span>
      <div>
        <div class="current-desc">{{ current.desc }} {{ current.wind }}</div>
        <div class="current-range">{{ current.low }}~{{ current.high }}°C
          <div :class="{
            'current-aqi': true, 'greenAqi': current.aqi <= 50,
            'yeallowAqi': current.aqi > 50 && current.aqi <= 100,
            'redAqi': current.aqi > 100
          }">{{ current.aqi }}{{ current.aqi <= 50 ? '优' : current.aqi > 50 && current.aqi <= 100 ? '良' : '差' }}</div>
          </div>
        </div>
        <div class="update-time">数据于 {{ current.updateTime }} 更新</div>
      </div>

      <!-- 小时温度折线图 -->
      <div class="hourly-chart-scroll">
        <div class="scroll-btn left" @click="scrollLeft" v-if="showLeftBtn">
          <img src="./assets/img/left.png" alt="">
        </div>
        <div class="hourly-chart-viewport" ref="scrollContainer">
          <div class="hourly-chart-inner" :style="{ minWidth: chartMinWidth }">
            <Line :data="chartData" :options="chartOptions" :width="chartMinWidthNum" :key="chartMinWidthNum" />
            <!-- 小时标签、天气图标、空气质量 -->
            <div class="hourly-x-labels" :style="{ width: temAllWidth, transform: `translateX(${tempTranslateX}px)` }">
              <div v-for="(h, idx) in hourly" :key="h.time" class="hourly-x-label" :style="{ width: temWidth }">
                <div class="hour-time">{{ h.time }}</div>
                <div class="hour-icon" style="margin-bottom: 85px;">
                  <img :src="`../src/assets/img/weather/${h.icon}.png`" :title="h.text"></img>
                </div>
                <div title="相对湿度" class="hour-aqi">{{ h.rh }}%</div>
              </div>
            </div>
          </div>
        </div>
        <div class="scroll-btn right" @click="scrollRight" v-if="showRightBtn">
          <img src="./assets/img/right.png" alt="">
        </div>
      </div>

      <!-- 7天预报 -->
      <div class="forecast15d-card" :style="{ height: rowsHeight }">
        <div class="forecast15d-header">
          <span>7天预报</span>
        </div>
        <div class="forecast15d-row" v-for="item in visibleForecast" :key="item.date">
          <div class="forecast15d-date">
            <div class="date-main">{{ item.date }}</div>
            <div class="date-label">{{ item.label }}</div>
          </div>
          <div class="forecast15d-weather">
            <!-- <div :class="'weather_icon weather_' + item.textImg"></div> -->
            <div class="weather-icon">
              <img :src="`../src/assets/img/weather/${item.icon}.png`"></img>
            </div>
            <span class="weather-desc">{{ item.desc }}</span>
          </div>

          <div class="temp-range">{{ item.tempLow }} ~ {{ item.tempHigh }}°</div>

          <div class="forecast15d-temp">

            <span class="aqi">{{ item.aqi }}</span>
          </div>

        </div>
        <div class="forecast15d-expand">
          <div class="forecast15d-expand-btn" @click="open15Days">{{ foldStatus ? '收起7天预报 ▲' : '展开7天预报 ▼' }}</div>
        </div>
      </div>
    </div>
    <div>
      <n-icon size="30" class="setting-wrapper" @click="showSetting = !showSetting">
        <svg t="1753932447440" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
          p-id="4819" width="32" height="32">
          <path
            d="M919.6 405.6l-57.2-8c-12.7-1.8-23-10.4-28-22.1-11.3-26.7-25.7-51.7-42.9-74.5-7.7-10.2-10-23.5-5.2-35.3l21.7-53.5c6.7-16.4 0.2-35.3-15.2-44.1L669.1 96.6c-15.4-8.9-34.9-5.1-45.8 8.9l-35.4 45.3c-7.9 10.2-20.7 14.9-33.5 13.3-14-1.8-28.3-2.8-42.8-2.8-14.5 0-28.8 1-42.8 2.8-12.8 1.6-25.6-3.1-33.5-13.3l-35.4-45.3c-10.9-14-30.4-17.8-45.8-8.9L230.4 168c-15.4 8.9-21.8 27.7-15.2 44.1l21.7 53.5c4.8 11.9 2.5 25.1-5.2 35.3-17.2 22.8-31.7 47.8-42.9 74.5-5 11.8-15.3 20.4-28 22.1l-57.2 8C86 408 72.9 423 72.9 440.8v142.9c0 17.7 13.1 32.7 30.6 35.2l57.2 8c12.7 1.8 23 10.4 28 22.1 11.3 26.7 25.7 51.7 42.9 74.5 7.7 10.2 10 23.5 5.2 35.3l-21.7 53.5c-6.7 16.4-0.2 35.3 15.2 44.1L354 927.8c15.4 8.9 34.9 5.1 45.8-8.9l35.4-45.3c7.9-10.2 20.7-14.9 33.5-13.3 14 1.8 28.3 2.8 42.8 2.8 14.5 0 28.8-1 42.8-2.8 12.8-1.6 25.6 3.1 33.5 13.3l35.4 45.3c10.9 14 30.4 17.8 45.8 8.9l123.7-71.4c15.4-8.9 21.8-27.7 15.2-44.1l-21.7-53.5c-4.8-11.8-2.5-25.1 5.2-35.3 17.2-22.8 31.7-47.8 42.9-74.5 5-11.8 15.3-20.4 28-22.1l57.2-8c17.6-2.5 30.6-17.5 30.6-35.2V440.8c0.2-17.8-12.9-32.8-30.5-35.2z m-408 245.5c-76.7 0-138.9-62.2-138.9-138.9s62.2-138.9 138.9-138.9 138.9 62.2 138.9 138.9-62.2 138.9-138.9 138.9z"
            fill="" p-id="4820"></path>
        </svg>
      </n-icon>
      <n-drawer v-model:show="showSetting" :width="250" placement="right" content-style="background-color: #F1F1F1"
        resizable>
        <div style="padding: 20px 20px; ">
          <h1 style="font-weight: 900;font-size: 20px;margin-bottom: 10px;">设置</h1>
          <n-flex class="item" :size="12" vertical>
            <n-flex align="center" justify="space-between">
              <span>启用桌面小控件</span>
              <n-switch size="small" v-model:value="desktopWidget.enable" @update-value="updateDesktopWidget" />
            </n-flex>

            <div v-if="desktopWidget.enable" style="width: 100%; height: 1px;background-color:#e3e3e3;"></div>
            <n-flex v-if="desktopWidget.enable" align="center" justify="space-between">
              <span>窗口穿透</span>
              <n-switch size="small" v-model:value="desktopWidget.penetrate" @update-value="updateDesktopPenetrate" />
            </n-flex>

            <div v-if="desktopWidget.enable" style="width: 100%; height: 1px;background-color:#e3e3e3;"></div>
            <n-flex v-if="desktopWidget.enable" align="center" justify="space-between">
              <span>透明度</span>
              <n-slider style="width: 100px;" size="small" v-model:value="desktopWidget.opacity" :step="0.1" :min="0"
                :max="1" @update-value="updateDesktopOpacity" />
            </n-flex>

            <div v-if="desktopWidget.enable" style="width: 100%; height: 1px;background-color:#e3e3e3;"></div>
            <n-flex v-if="desktopWidget.enable" align="center" justify="space-between">
              <span>窗口大小</span>
              <n-slider style="width: 100px;" size="small" v-model:value="desktopWidget.winSize" :step="1" :min="10"
                :max="100" @update-value="updateDesktopSize" />
            </n-flex>
            <div v-if="desktopWidget.enable" style="width: 100%; height: 1px;background-color:#e3e3e3;"></div>
            <n-flex v-if="desktopWidget.enable" align="center" justify="space-between">
              <span>窗口位置</span>
              <n-select style="width: 100px;font-size: 16px;" v-model:value="desktopWidget.location" label-field="label"
                placeholder="请选择" :options="locationOptions" @update-value="updateDesktopPosition" />
            </n-flex>
          </n-flex>
        </div>
      </n-drawer>
    </div>
</template>

<script setup lang="ts">
import { computed, nextTick, onMounted, onUnmounted, ref } from 'vue'
import { Line } from 'vue-chartjs'
import { useWindow } from './hooks/useWindows'
import { Store } from '@tauri-apps/plugin-store';
import axios from 'axios'
import ChartDataLabels from 'chartjs-plugin-datalabels'
import ActionBar from './components/ActionBar.vue'
import dayjs from 'dayjs'
import { weatherCode } from './enums/weatherCode';
import { NCascader, NIcon, NDrawer, NFlex, NSwitch, NSlider, NSelect } from 'naive-ui'
import { inject, watch } from 'vue'
import { invoke } from "@tauri-apps/api/core";



import {
  Chart as ChartJS,
  CategoryScale,
  LinearScale,
  PointElement,
  LineElement,
  Tooltip,
  Legend
} from 'chart.js'
import { emit } from '@tauri-apps/api/event';

const showSetting = ref(false);
const cityOptions = ref([])
const showLeftBtn = ref(false)
const showRightBtn = ref(false)
// 折叠状态
const foldStatus = ref(false);
// 组件窗口配置
const desktopWidget = ref({
  enable: true,
  penetrate: true,
  opacity: 1,
  winSize: 20,
  location: 'top-right',
});


const { createWebviewWindow, setWinPosition, closWebviewWindow,
  setWebviewWindowSize, setWinPositionByLable, setWebviewWindowPenetrate } = useWindow();

//const router = inject('router') as any
ChartJS.register(CategoryScale, LinearScale, PointElement, LineElement, Tooltip, Legend, ChartDataLabels)

const scrollContainer = ref<HTMLElement | null>(null)

const handleLoad = (options: any) => {
  return new Promise<void>(async (resolve) => {
    const response = await axios.post("/api/area/fetchCityCodes", { code: options.value });
    options.children = response.data.data.map((city: any) => {
      return {
        label: city.name,
        value: city.code,
        isLeaf: city.level >= 2,
      }
    });
    resolve()
  })
}
const weatherAll = ref<any>();
const city = ref({
  value: '',
  label: ''
})

const findByCityCde = (cityCode: any) => {
  for (let i = 0; i < cityOptions.value.length; i++) {
    const li: any = cityOptions.value[i];
    if (li.value.slice(0, 2) == cityCode.slice(0, 2)) {
      // 找到省份
      for (let j = 0; j < (li.children?.length || 0); j++) {
        const child = li.children[j];
        if (child.value.slice(0, 4) == cityCode.slice(0, 4)) {
          // 找到市
          for (let k = 0; k < (child.children?.length || 0); k++) {
            const chi = child.children[k];
            if (chi.value == cityCode) {
              // 找到区
              return chi;
            }
          }
        }
      }
    }
  }
}

const handleCityUpdate = async (cityCode: any) => {
  const cityData = findByCityCde(cityCode);
  // 保存已选择城市
  const store = await Store.load(__PLUGIN_NAME__ + ".json");
  await store.set("lastCity", JSON.stringify(cityData))
  fetchWeather(cityCode);
}

const updateDesktopWidget = async (value: any) => {
  if (value) {
    openWindow()
  } else {
    closeWindow();
  }
  saveWidgetSettings()
}

// 窗口穿透
const updateDesktopPenetrate = async (value: any) => {
  // 设置窗口大小
  setWebviewWindowPenetrate("desktopWidget", value);
  saveWidgetSettings()
}

// 更新透明度
const updateDesktopOpacity = async (value: any) => {
  // 发布事件更新透明度
  emit("updateDesktopOpacity", value)
  saveWidgetSettings()
}

// 更新窗口大小
const updateDesktopSize = async (value: any) => {
  // 设置窗口大小
  setWebviewWindowSize("desktopWidget", value * 10, value * 10);
  saveWidgetSettings()
}

// 更新窗口位置
const updateDesktopPosition = async (value: any) => {
  await setWinPositionByLable("desktopWidget", value)
  saveWidgetSettings()
}

// 保存桌面小控件设置项
const saveWidgetSettings = async () => {
  const store = await Store.load(__PLUGIN_NAME__ + ".json");
  await store.set("desktopWidget", JSON.stringify(desktopWidget.value))
}



const locationOptions = ref([
  { label: '右上角', value: 'top-right' },
  { label: '左上角', value: 'top-left' },
  { label: '左下角', value: 'bottom-left' },
  { label: '右下角', value: 'bottom-right' },
  { label: '居中', value: 'center' }
])

const current = ref({
  temp: 0,
  desc: '阴',
  wind: '东风1级',
  low: 0,
  high: 0,
  aqi: 0,
  updateTime: '00:00',
  alert: ''
})

watch(current, (value) => {
  emit("currentWeatherChange", value)
})

const forecast15d = ref<any>([])

const visibleForecast = computed(() => foldStatus.value ? forecast15d.value.slice(0, 7) : forecast15d.value.slice(0, 5))
const rowsHeight = computed(() => `${visibleForecast.value.length * 50 + 88}px`);
const hourly = ref<any>([])

const labelWidth = ref(80);
const chartMinWidthNum = computed(() => hourly.value.length * labelWidth.value)
const chartMinWidth = computed(() => `${chartMinWidthNum.value}px`)

const temWidth = computed(() => `${(hourly.value.length * labelWidth.value - 100) / (hourly.value.length - 1)}px`)
const temAllWidth = computed(() => `${(hourly.value.length * labelWidth.value - 100) / (hourly.value.length - 1) * hourly.value.length}px`)
const tempTranslateX = computed(() => 50 - (labelWidth.value / 2))


const chartData = computed(() => ({
  labels: hourly.value.map((h: any) => h.time),
  datasets: [
    {
      label: '温度',
      data: hourly.value.map((h: any) => h.temp),
      borderColor: '#1976d2',
      backgroundColor: 'rgba(25, 118, 210, 0.08)',
      tension: 0.4,
      pointRadius: 5,
      pointBackgroundColor: '#1976d2',
      pointBorderColor: '#fff',
      pointBorderWidth: 2,
      fill: false
    }
  ]
}))

const chartOptions = ref<any>({
  responsive: true,
  maintainAspectRatio: false,
  layout: {
    padding: {
      top: 50, // 适当增大
      left: 50,
      right: 50,
      bottom: 50
    }
  },
  plugins: {
    legend: { display: false },
    tooltip: {
      enabled: true,
    },
    datalabels: {
      display: true,
      color: '#1976d2',
      align: 'top',
      anchor: 'center',
      formatter: (value: number) => `${value}°`
    }
  },
  scales: {
    x: {
      display: false // 不显示x轴
    },
    y: {
      display: false // 不显示y轴
    }
  }
})

const scrollLeft = () => {
  if (scrollContainer.value) {
    scrollContainer.value.scrollLeft -= 3 * labelWidth.value;
    setTimeout(updateBtnVisible, 300)
  }
}

const scrollRight = () => {
  if (scrollContainer.value) {
    scrollContainer.value.scrollLeft += 3 * labelWidth.value;
    setTimeout(updateBtnVisible, 300)
  }
}

const updateBtnVisible = () => {
  const el = scrollContainer.value
  if (!el) return
  showLeftBtn.value = el.scrollLeft > 0
  // 容差2像素，防止小数点误差
  showRightBtn.value = el.scrollLeft + el.clientWidth < el.scrollWidth - 2;
}

const updateContainerWidth = () => {
  if (scrollContainer.value) {
    const labelWid = scrollContainer.value.clientWidth / hourly.value.length;
    if (labelWid < 80) {
      labelWidth.value = 80
    } else if (labelWid > 100) {
      labelWidth.value = 100
    } else {
      labelWidth.value = labelWid;
    }
  }
}

const open15Days = () => {
  foldStatus.value = !foldStatus.value;
}

// 初始化操作
const init = async () => {
  // 获取省
  const response = await axios.post("/api/area/fetchCityCodes", {});
  cityOptions.value = response.data.data.map((city: any) => {
    return {
      label: city.name,
      value: city.code,
      isLeaf: false,
    }
  });
  // 加载本地缓存
  const store = await Store.load(__PLUGIN_NAME__ + ".json");
  const lastCity: any = await store.get("lastCity")
  const desktopWidgetCache: any = await store.get("desktopWidget")

  if (typeof desktopWidgetCache != 'undefined') {
    desktopWidget.value = JSON.parse(desktopWidgetCache);
    if (desktopWidget.value.enable) {
      // 启动小组件
      openWindow()
    }
  } else {
    // 使用默认值 启动小组件
    openWindow()
  }

  let cityCode = '';
  if (lastCity) {
    const lastCityObj = JSON.parse(lastCity);
    city.value.value = lastCityObj.label;
    city.value.label = lastCityObj.label;
    cityCode = lastCityObj.value;
  } else {
    city.value.value = "东城区";
    city.value.label = "东城区";
    cityCode = '110101'
  }
  // 启动定时每10分钟拉取一个
  setInterval(() => {
    console.log("aaa")
    fetchWeather(cityCode);
  }, 600000)
  fetchWeather(cityCode);
}

const fetchWeather = async (cityCode: any) => {
  // 获取天气
  const weatherRes = await axios.post("/api/weather/fetchWeather", { 'weatherLocal': cityCode });
  if (weatherRes.data.data.result) {
    weatherAll.value = weatherRes.data.data.result;
    console.log("获取当前天气:", weatherRes.data.data.result)
    // 解析当前天气
    parseWeather(weatherRes.data.data.result);
    // 更新按钮
    nextTick(() => {
      updateBtnVisible()
    })
  }
}

const parseWeather = (weatherRes: any) => {
  const updateTime = dayjs(weatherRes.now.uptime, 'YYYYMMDDHHmmss').format('HH:mm');
  let alert = '';
  if (weatherRes.alerts && weatherRes.alerts.length > 0) {
    alert = weatherRes.alerts[0].title
  }
  current.value = {
    temp: weatherRes.now.temp,
    desc: weatherRes.now.text,
    wind: weatherRes.now.wind_dir + weatherRes.now.wind_class,
    low: weatherRes.forecasts[0].low,
    high: weatherRes.forecasts[0].high,
    aqi: weatherRes.now.aqi,
    updateTime,
    alert
  }

  const fetchWeatherIcon = (text: string) => {
    return weatherCode.get(text)
  }

  // { time: '现在', temp: 31, icon: '🌥️', aqi: '优' },
  const hourlyData = weatherRes.forecast_hours.map(((li: any) => {
    return {
      time: dayjs(li.data_time, 'YYYY-MM-DD HH:mm:ss').format('HH:mm'),
      temp: li.temp_fc,
      text: li.text,
      icon: fetchWeatherIcon(li.text),
      rh: li.rh,
      aqi: '优'
    }
  }))
  // 小时播报
  hourly.value = hourlyData

  // 天气预报
  // { date: '07/15', label: '昨天', desc: '多云', icon: '⛅', tempLow: 26, tempHigh: 34, aqi: '优' },
  const forecastData = weatherRes.forecasts.map(((li: any, index: any) => {
    return {
      date: dayjs(li.date, 'YYYY-MM-DD').format('MM/DD'),
      label: index == 0 ? '今天' : li.week.replace("星期", "周"),
      desc: li.text_day,
      icon: fetchWeatherIcon(li.text_day),
      tempLow: li.low,
      tempHigh: li.high,
      aqi: '优'
    }
  }))
  forecast15d.value = forecastData

}

const openWindow = async () => {
  const store = await Store.load(__PLUGIN_NAME__ + ".json");
  const desktopWidgetPositionCache: any = await store.get("desktopWidgetPosition")

  // 在窗口的左上角
  const win = await createWebviewWindow("桌面组件", "desktopWidget", 200, 200, true, false, 200, 200, false, false);
  // 等待50ms
  await delay(50)
  // 开启穿透（忽略鼠标事件）
  await win.setIgnoreCursorEvents(desktopWidget.value.penetrate);
  // 设置位置
  if (desktopWidgetPositionCache) {
    await setWinPositionByLable("desktopWidget", JSON.parse(desktopWidgetPositionCache))
  } else {
    await setWinPosition(win, desktopWidget.value.location)
  }
  // 设置大小
  await setWebviewWindowSize("desktopWidget", desktopWidget.value.winSize * 10, desktopWidget.value.winSize * 10);

  //win.maximize()
}

const closeWindow = async () => {
  await closWebviewWindow("desktopWidget");
}

function delay(ms: number) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

onMounted(() => {
  init();
  updateContainerWidth();
  window.addEventListener('resize', updateBtnVisible)
  window.addEventListener('resize', updateContainerWidth)
})

onUnmounted(() => {
  window.removeEventListener('resize', updateBtnVisible)
  window.removeEventListener('resize', updateContainerWidth)
})
</script>

<style scoped>
.weather-panel {
  margin: 0 auto;
  box-shadow: 0 4px 24px rgba(0, 0, 0, 0.08);
  background: linear-gradient(to bottom, #cbe5ff 0%, #eaf3fa 100%);
  padding: 30px 24px;
  height: calc(100vh - 60px);
  font-family: 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', Arial, sans-serif;
  overflow-y: scroll;
  user-select: none;
}

.weather-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
}

:deep(.n-base-selection-label) {
  background: transparent !important;
}

:deep(.n-base-selection__border) {
  border: unset !important;
}

:deep(.weather-header .n-base-selection-input__content) {
  font-size: 20px;
  font-weight: bold;
}

:deep(.n-base-selection__state-border) {
  border: unset !important;
  box-shadow: unset !important;
}

:deep(.n-base-selection .n-base-suffix .n-base-suffix__arrow) {
  --n-arrow-color: rgb(51, 54, 57);
}

.city {
  width: 150px;
}

.setting-wrapper {
  position: fixed;
  bottom: 20px;
  color: #2b2b2b;
  right: 20px;
  background-color: #d1d1d1;
  padding: 5px;
  border-radius: 50px;
  cursor: pointer;
  transition: all 0.3s ease;
}

.setting-wrapper:hover {
  transform: rotate(90deg);
  background-color: #b8b8b8;
}

.alert {
  background: #fffbe6;
  color: #bfa100;
  font-size: 0.85rem;
  padding: 8px 12px;
  border-radius: 12px;
}

.update-time {
  font-size: 13px;
  color: #888;
  position: absolute;
  top: 25px;
  right: 10px;
}

.weather-current {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-bottom: 12px;
  position: relative;
}

.current-temp {
  font-size: 65px;
  font-weight: bold;
  line-height: 1;
}

.current-desc {
  font-size: 16px;
  margin-bottom: 5px;
}

.current-range {
  display: flex;
  align-items: center;
  gap: 10px;
  height: 25px;
  font-size: 22px;
  color: #666;
}

.current-aqi {
  border-radius: 8px;
  padding: 4px 8px;
  font-size: 14px;
}

.greenAqi {
  background: #e6ffe6;
  color: #1a7f1a;
}

.yeallowAqi {
  background: #F0BC00;
  color: #FFF;
}

.redAqi {
  background: #F56B7C;
  color: #FFF;
}

.hourly-chart-scroll {
  position: relative;
  width: 100%;
  display: flex;
  align-items: center;
  overflow: visible;
}

.hourly-chart-viewport {
  overflow: hidden;
  scroll-behavior: smooth;
  width: 100%;
  height: 100%;
}

.hourly-chart-inner {
  margin-top: 50px;
  height: 150px;
  width: max-content;
  position: relative;
}

.hourly-chart-inner canvas {
  position: relative;
  z-index: 1;
}

.hourly-x-labels {
  display: flex;
  justify-content: flex-start;
  align-items: flex-start;
  position: absolute;
  left: 0px;
  right: 0px;
  bottom: 0;
  height: 200px;
  z-index: 2;
}

.hourly-x-label {
  text-align: center;
  font-size: 13px;
  color: #666;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.hourly-x-label:hover {
  background: rgba(25, 118, 210, 0.12);
  border-radius: 12px;
  box-shadow: 0 2px 8px rgba(25, 118, 210, 0.08);
}

.hour-time {
  margin-top: 10px;
  font-size: 16px;
  margin-bottom: 10px;
}

.hour-icon {
  font-size: 18px;
  margin-bottom: 110px;
}

.hour-temp {
  font-size: 13px;
  color: #1976d2;
  margin-bottom: 2px;
}

.scroll-btn {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  background-color: #fff;
  height: 32px;
  width: 32px;
  border-radius: 16px;
  opacity: .8;
  cursor: pointer;
  box-shadow: 0 4px 4px 0 rgba(0, 0, 0, .1);
  z-index: 3;
  text-align: center;
  -webkit-user-select: none;
  user-select: none;
  display: flex;
  align-items: center;
  justify-content: center;
}

.scroll-btn img {
  width: 15px;
  height: 15px;
}

.scroll-btn:hover {
  opacity: 1;
}

.left {
  left: 0;
}

.right {
  right: 0;
}

.hour-aqi {
  font-size: 14px;
  color: #1a7f1a;
  background: #e6ffe6;
  border-radius: 8px;
  padding: 6px 10px;
  margin-bottom: 10px;
}

.forecast15d-card {
  background: #fff;
  border-radius: 16px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
  padding: 8px 0 0 0;
  margin: 24px 0 0 0;
  transition: height 0.5s cubic-bezier(0.22, 1, 0.36, 1);
}

.forecast15d-header {
  padding: 10px 16px;
  font-size: 16px;
  font-weight: bold;
}


.forecast15d-row {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 48px;
  padding: 0 30px;
  border-bottom: 1px solid #f0f0f0;

}

.forecast15d-row:last-child {
  border-bottom: none;
}

.forecast15d-row:hover {
  background-color: #f2f3f5;
}

.forecast15d-date {
  display: flex;
  gap: 35px;
  align-items: center;
  text-align: left;
  color: #888;
  font-size: 16px;
}

.date-main {
  font-weight: bold;
  color: #222;
}

.date-label {
  font-size: 14px;
  color: #1f1f24;
}

.forecast15d-weather {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 8px;
  justify-content: center;
}

.weather-icon img {
  width: 30px;
  height: 30px;
}

.weather-desc {
  width: 100px;
  font-size: 15px;
  color: #444;
}

.forecast15d-temp {
  width: 90px;
  text-align: right;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
}

.temp-range {
  font-size: 18px;
  color: #1976d2;
}

.aqi {
  background: #e6ffe6;
  color: #1a7f1a;
  border-radius: 8px;
  padding: 6px 10px;
  font-size: 14px;
}

.forecast15d-expand {
  display: flex;
  justify-content: center;
  width: 100%;
  color: #1f1f24;
  text-align: center;
  padding: 8px 0 12px 0;
}

.forecast15d-expand-btn {
  width: 60%;
  border-radius: 9px;
  line-height: 32px;
  height: 32px;
  background-color: #f2f3f5;
  border: none;
  font-size: 15px;
  cursor: pointer;
  user-select: none;
}

.forecast15d-expand-btn:hover {
  color: #315efb;
  background: rgba(49, 94, 251, .1);
}

.weather-panel::-webkit-scrollbar {
  width: 6px;
  transition-property: opacity;
  transition-duration: 0.3s;
  transition-timing-function: ease;
}

.weather-panel::-webkit-scrollbar-thumb {
  background-color: rgba(144, 144, 144, 0.7);
  border-radius: 3px;
  transition-property: opacity, background-color;
  transition-duration: 0.3s;
  transition-timing-function: ease;
  min-height: 75px;
}

.weather-panel::-webkit-scrollbar-thumb:hover {
  background-color: rgba(144, 144, 144, 1);
}

.weather-panel::-webkit-scrollbar-track {
  background: transparent;
}

.hour-icon img {
  width: 40px;
  height: 40px;
}

.item {
  box-sizing: border-box;
  width: 100%;
  height: 100%;
  border-width: 1px;
  border-color: #e3e3e3;
  border-radius: 12px;
  border-style: solid;
  background-color: #fdfdfd;
  padding: 12px;
  box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
}
</style>